#include <iostream>
#include <purg.h>

template <int i>
class binary
{
  public:
    enum { result = i%10 + 2 * binary<i/10>::result };
};

template <>
class binary<0>
{
  public:
    enum { result = 0 };
};

typedef purg::single_byte_stream_tmpl<binary<10101010>::result,20>  even;
typedef purg::single_byte_stream_tmpl<binary<1010101>::result,4>    odd;
typedef purg::single_byte_stream_tmpl<binary<10000000>::result,20>  first;
typedef purg::single_byte_stream_tmpl<binary<1111111>::result,4>    rest;

typedef purg::combined_generator_tmpl<even,odd>    gen1;
typedef purg::combined_generator_tmpl<first,rest>  gen2;

template <typename POD>
void  out_bits ( POD a )
{
  unsigned char *t = reinterpret_cast<unsigned char *> (&a);
  for ( size_t i = 0 ; i != sizeof ( POD ) ; i++ )
  {
    for ( size_t j = 0 ; j != 8 ; j++ )
    {
      if ( t[i] % 2 )
        std::cout << "1";
      else
        std::cout << "0";
      t[i] /= 2;
    }
  }
  std::cout << std::endl;
}

template <typename POD,typename GEN>
void  exercise ()
{
  POD  expected;
  unsigned char *t = reinterpret_cast<unsigned char *> (&expected);
  for ( size_t i = 0 ; i != sizeof ( POD ) ; i++ )
  {
    t[i] = 255;
  }
  std::cout << "--------------\nNew Test:\n Expected value: " << expected << std::endl;
  size_t numRight = 0;
  GEN  generator ( 1 , 1 , 1 );
  for ( size_t i = 0 ; i != 1000000 ; i++ )
  {
    POD a;
    generator.get ( a );
    if ( a == expected )
      numRight++;
    else
      out_bits ( a );
  }
  std::cout << " Fraction correct: " << numRight << " / 1000000\n";
}

template <typename GEN>
void go ()
{
  exercise<unsigned char,GEN> ();
  exercise<unsigned int,GEN> ();
  exercise<unsigned long,GEN> ();
  exercise<unsigned long long,GEN> ();
}

int main ( int argc , char ** argv )
{
  go<gen1>();
  go<gen2>();
}

